package com.hyc.config;

import com.hyc.annotation.EnableFinishRpcServer;
import com.hyc.annotation.FinishService;
import com.hyc.constant.RpcConstant;
import com.hyc.netty.server.NettyRpcServer;
import com.hyc.provider.ServiceProvider;
import com.hyc.util.ConfigLoader;
import org.reflections.Reflections;

import java.lang.annotation.Annotation;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author 冷环渊
 * 用于读取并初始化对应节点的注解操作
 * @date 2025/6/18 16:49
 * @description RpcAutoConfiguration
 */
public class RpcAutoConfiguration {
    private static RpcConfigTemplate rpcConfigTemplate;

    static {
        scanAndInitServer();
    }

    public static RpcConfigTemplate rpcConfigStart() {
        if (rpcConfigTemplate == null) {
            init();
        }
        return rpcConfigTemplate;
    }

    private static void scanAndInitServer() {
        try {
            String callerPackage = getCallerPackage();
            System.out.println("扫描包名" + callerPackage);
            EnableFinishRpcServer enableFinish = scanService(callerPackage, EnableFinishRpcServer.class).getAnnotation(EnableFinishRpcServer.class);
            List<Object> finishServices = scanServices(callerPackage, FinishService.class);
            if (enableFinish.useDefaultConfig()) {
                init(new RpcConfigTemplate());
            } else {
                init();
            }
            System.out.println("配置文件加载完成 开始注解初始化");
            if (!finishServices.isEmpty()) {
                for (Object finishService : finishServices) {
                    FinishService annotation = finishService.getClass().getAnnotation(FinishService.class);
                    ServiceProvider serviceProvider = new ServiceProvider(new InetSocketAddress(rpcConfigTemplate.getHost(), rpcConfigTemplate.getPort()));
                    if (!annotation.serviceName().isEmpty()) {
                        serviceProvider.providerServiceInterface(annotation.serviceName(), finishService, String.valueOf(annotation.canRetry()));
                        NettyRpcServer rpcServer = new NettyRpcServer(serviceProvider);
                        rpcServer.start(rpcConfigTemplate.getPort());
                    } else {
                        serviceProvider.providerServiceInterface(finishService, String.valueOf(annotation.canRetry()));
                        NettyRpcServer rpcServer = new NettyRpcServer(serviceProvider);
                        rpcServer.start(rpcConfigTemplate.getPort());
                    }
                }
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("未找到注解 rpc没有成功初始化");
        }
    }

    private static void init() {
        RpcConfigTemplate custom = ConfigLoader.loadConfig(RpcConfigTemplate.class, RpcConstant.CONFIG_PREFIX);
        init(custom);
    }

    private static void init(RpcConfigTemplate custom) {
        rpcConfigTemplate = custom;
        System.out.println("rpc初始化 配置 = " + custom);
    }

    /**
     * 扫描主类包 入口类
     * * @author 冷环渊
     * date: 2025/6/18 16:54
     */
    public static String getCallerPackage() throws ClassNotFoundException {
        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
        String className = stackTrace[stackTrace.length - 1].getClassName();
        Class<?> mainClass = Class.forName(className);
        return mainClass.getPackage().getName();
    }


    public static List<Object> scanServices(String basePackage, Class<? extends Annotation> annotationClass) {
        //拿到反射实例 扫描基础包
        Reflections reflections = new Reflections(basePackage);

        //使用 get
        Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(annotationClass);
        List<Object> objects = new ArrayList<>();
        for (Class<?> aClass : typesAnnotatedWith) {
            try {
                objects.add(aClass.newInstance());
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return objects;
    }

    public static Class<?> scanService(String basePackage, Class<? extends Annotation> annotationClass) {
        //拿到反射实例 扫描基础包
        Reflections reflections = new Reflections(basePackage);
        Class<?> res = null;
        //使用 get
        Set<Class<?>> typesAnnotatedWith = reflections.getTypesAnnotatedWith(annotationClass);
        for (Class<?> aClass : typesAnnotatedWith) {
            res = aClass;
        }
        return res;
    }
}
